package org.mipt.infsec.steganography.impl.petzib;

import org.mipt.infsec.steganography.api.ImageEncryptor;
import org.mipt.infsec.steganography.api.datastorage.Bit;
import org.mipt.infsec.steganography.impl.petzib.keys.KeyGeneratorImpl;
import org.mipt.infsec.steganography.impl.petzib.keys.KeyImpl;
import org.mipt.infsec.steganography.utils.ConvertUtils;

import javax.imageio.ImageIO;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;

public class EncryptorImpl extends ImageEncryptor
{
    /**
     * Default constructor
     */
    public EncryptorImpl()
    {
    }

    /**
     * @see ImageEncryptor
     * @param file - file which contains in picture
     * @param data - data which will be hidden in the input picture
     * @throws IOException occurs when IO-problem with file
     */
    public EncryptorImpl(File file, String data) throws IOException
    {
        super(file, data);
    }

    /**
     * @see ImageEncryptor
     * @param is InputStream which contains an image
     * @param data which will be hidden in the input stream
     * @throws IOException occurs when IO-problem with file
     */
    public EncryptorImpl(InputStream is, String data) throws IOException
    {
        super(is, data);
    }

    /**
     * Hide data in image according to PetZib algo
     */
    @Override
    public Object encrypt()
    {
        Bit[] bits = ConvertUtils.stringToBits(getData());

        KeyImpl[] keys = (KeyImpl[])(KeyGeneratorImpl.getInstance().generateKeys(Math.min(getImage().getWidth(), bits.length)));

        for (int i = 0; i < Math.min(getImage().getWidth() , bits.length); i++)
        {
            for (int j = keys[i].getValue(); j < getImage().getHeight(); j += keys[i].getValue())
            {
                int[] RGB = getImage().getPixel(i, j);
                if (bits[i].isUNIT())
                {
                    RGB[2] = RGB[2] + (int)(0.1 * (0.3 * RGB[0] + 0.59 * RGB[1] + 0.11 * RGB[2]));
                    if (RGB[2] > 255) RGB[2] = 255;
                } else {
                    RGB[2] = RGB[2] - (int)(0.1 * (0.3 * RGB[0] + 0.59 * RGB[1] + 0.11 * RGB[2]));
                    if (RGB[2] < 0) RGB[2] = 0;
                }
                getImage().setPixel(i, j, RGB);
            }
        }
        try{
            getImage().write(getOutFile());
            String[] strings = KeyImpl.hideKeys(keys);
            StringBuffer sb = new StringBuffer("");
            for (int i = 0; i < strings.length; i++)
                sb = sb.append(strings[i]).append(" ");
            return sb.toString();
        } catch(Exception e)
        {
            e.printStackTrace();
        }
        return "";
    }
}
